package com.second.app.thread.线程基础.day08;

import org.apache.commons.lang3.StringUtils;

import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author GYZ
 * @Date 2023/11/30
 * <pre>
 *   join: 使所属得线程对象x正常执行run方法中得任务，而使当前线程z进行无限期得阻塞
 *         等待线程x销毁后再继续执行线程z后面的代码。
 *   join具有使线程排队运行的作用。
 *   join原理是在内部：使用wait()方法进行等待，而synchronized使用的是"对象监视器"原理做同步
 *
 *   //案例2
 *   join如果遇到异常
 *     现有线程A,B,C ，先启动线程B,线程B负责启动线程A，并且线程Bx需要等待线程A执行完毕，方可执行后续逻辑
 *     线程C启动负责中断线程B
 *     join()遇到interrupt()如果彼此遇到，则会出现异常。但是进程按钮还呈现”红色“，原因是线程ThreadA还在继续运行
 *     ，线程ThreadA并未出现异常，是正常执行的状态。
 *   //案例3
 *      证明sleep(time)不释放锁：
 *      线程A执行后启动线程B,线程B启动后休眠5秒，线程A一直持有线程B对象锁，休眠了6s才释放线程B对象锁，
 *      此时线程C拿到线程B对象锁，调用ThreadB中的同步方法。
 *   //案例4
 *      证明join(time)会释放锁,线程A执行后启动线程B,线程B启动后休眠5秒，线程A此时持有线程B对象锁，线程B执行完成后，线程A继续执行后续逻辑
 *      但是ThreadB另外的同步方法打印先于线程A执行结束日志打印，所以可以推出join是释放锁的。
 *   //案例5
 *       join后面的代码提前运行（出现意外）
 *       线程A执行完成，释放锁。此时b线程执行，按道理来说应该等待b线程执行2s后，才可以执行主线程后面的逻辑
 *       但是提前执行了。
 *       意外原因：比如b.join()率先抢到了锁。然后线程释放锁，此时发现join(2s)已经超时，所以输出main end 在
 *       线程B抢到锁打印线程b begin之前。
 *  //案例6
 *      ThreadLocal 参考文章 https://juejin.cn/post/7250734439709458469 由此引出
 *      强引用，软引用，弱引用。
 *  //案例7
 *     ThreadLocal
 *            验证数据的隔离性
 * </pre>
 */
class Demo7 {
    public static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        class ThreadA extends Thread {

            @Override
            public void run() {
                threadLocal.set("线程：" + Thread.currentThread().getName() + ",存放值100");
                System.out.println("线程：" + Thread.currentThread().getName() + "获取值：" + threadLocal.get());
            }
        }

        class ThreadB extends Thread {
            @Override
            public void run() {
                threadLocal.set("线程：" + Thread.currentThread().getName() + ",存放值200");
                System.out.println("线程：" + Thread.currentThread().getName() + "获取值：" + threadLocal.get());
            }
        }

        ThreadA threadA = new ThreadA();
        threadA.setName("线程A");
        threadA.start();

        ThreadB threadB = new ThreadB();
        threadB.setName("线程B");
        threadB.start();

    }
}

//案例6
class Demo6 {
    public static void main(String[] args) {
        //软引用1
        SoftReference<byte[]> soft1Reference = new SoftReference<>(new byte[1024 * 1024 * 10]);
        byte[] bytes = soft1Reference.get();
        //软引用2
        SoftReference<List<String>> soft2Reference = new SoftReference<>(new ArrayList<>());
        List<String> list = soft2Reference.get();
        //软引用特点：再系统将要发生内存溢出异常之前，将会把这些对象实例列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存，才会抛出内存溢出异常。
        //          也就是当jvm垃圾回收时,第一次回收内存足够，那么就不会回收软引用对象。如果第一次回收内存依然不够，那么就会回收掉软引用对象。
        //          软引用可以用来当作缓存，当系统内存足够时，通过缓存获取值。如果内存不够，先回收掉缓存，释放一定的内存空间,延迟oom。

        //弱引用：描述非必需对象的（它的强度比软引用更弱一些），被弱引用关联的对象实例只能生存到下一次垃圾收集发生之前。
        //        当垃圾收集器工作时，无论当前内存是否足够，都会回收掉只被弱引用关联的对象实例
    }
}

class Demo5 {
    public static void main(String[] args) {

        class ThreadB extends Thread {
            @Override
            synchronized public void run() {
                try {
                    System.out.println("begin B ThreadName=" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
                    Thread.sleep(5000);
                    System.out.println("end B ThreadName=" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        class ThreadA extends Thread {
            private final ThreadB threadB;

            public ThreadA(ThreadB threadB) {
                this.threadB = threadB;
            }

            @Override
            public void run() {
                synchronized (threadB) {
                    try {
                        System.out.println("begin A ThreadName=" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
                        Thread.sleep(5000);
                        System.out.println("end A ThreadName=" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        try {
            ThreadB threadB = new ThreadB();
            ThreadA threadA = new ThreadA(threadB);
            threadA.start();
            threadB.start();
            threadB.join(2000);
            System.out.println("   main end " + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

class Demo4 {
    public static void main(String[] args) {

        class ThreadB extends Thread {
            @Override
            public void run() {
                try {
                    System.out.println("b run begin time=" + System.currentTimeMillis());
                    Thread.sleep(5000);
                    System.out.println("b run end time=" + System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            synchronized public void bService() {
                System.out.println(" 打印 bService Timer=" + System.currentTimeMillis());
            }
        }

        class ThreadA extends Thread {
            private final ThreadB b;

            public ThreadA(ThreadB threadB) {
                this.b = threadB;
            }

            @Override
            public void run() {
                try {
                    synchronized (b) {
                        b.start();
                        b.join();
                        System.out.println("a run  end time =" + System.currentTimeMillis());
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        class ThreadC extends Thread {
            private final ThreadB threadB;

            public ThreadC(ThreadB threadB) {
                this.threadB = threadB;
            }

            @Override
            public void run() {
                threadB.bService();
            }
        }

        try {
            ThreadB threadB = new ThreadB();
            ThreadA threadA = new ThreadA(threadB);
            threadA.start();
            Thread.sleep(1000);
            ThreadC threadC = new ThreadC(threadB);
            threadC.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

//案例3
class Demo3 {
    public static void main(String[] args) {
        class ThreadB extends Thread {
            @Override
            public void run() {
                try {
                    System.out.println("b run begin time=" + System.currentTimeMillis());
                    Thread.sleep(5000);
                    System.out.println("b run end time=" + System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            synchronized public void bService() {
                System.out.println(" 打印 bService Timer=" + System.currentTimeMillis());
            }
        }

        class ThreadA extends Thread {
            private final ThreadB b;

            public ThreadA(ThreadB threadB) {
                this.b = threadB;
            }

            @Override
            public void run() {
                try {
                    synchronized (b) {
                        b.start();
                        Thread.sleep(6000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        class ThreadC extends Thread {
            private final ThreadB threadB;

            public ThreadC(ThreadB threadB) {
                this.threadB = threadB;
            }

            @Override
            public void run() {
                threadB.bService();
            }
        }

        try {
            ThreadB threadB = new ThreadB();
            ThreadA threadA = new ThreadA(threadB);
            threadA.start();
            Thread.sleep(1000);
            ThreadC threadC = new ThreadC(threadB);
            threadC.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        class ThreadJoin extends Thread {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " begin:" + System.currentTimeMillis());
                for (int i = 0; i < 10; i++) {
                    System.out.println("打印i值：" + (i + 1));
                }
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " end:" + System.currentTimeMillis());
            }
        }

        try {
            ThreadJoin threadJoin = new ThreadJoin();
            threadJoin.setName("join--线程");
            threadJoin.start();

            threadJoin.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main thread end");
    }
}

//案例2
class Test {
    public static void main(String[] args) {
        class ThreadA extends Thread {
            @Override
            public void run() {
                for (int i = 0; i < Integer.MAX_VALUE; i++) {
                    String newString = new String();
                    Math.random();
                }
            }
        }

        class ThreadB extends Thread {
            @Override
            public void run() {
                try {
                    ThreadA threadA = new ThreadA();
                    threadA.start();
                    threadA.join();
                    System.out.println("线程B 在 run end 处打印了 ");
                } catch (InterruptedException e) {
                    System.out.println("线程B 在 catch处打印了 ");
                    e.printStackTrace();
                }
            }
        }
        class ThreadC extends Thread {
            private ThreadB threadB;

            public ThreadC(ThreadB threadB) {
                this.threadB = threadB;
            }

            @Override
            public void run() {
                threadB.interrupt();
            }
        }

        try {
            ThreadB threadB = new ThreadB();
            threadB.start();
            Thread.sleep(500);
            ThreadC threadC = new ThreadC(threadB);
            threadC.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}



